package com.baohua.service.impl;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;

import com.baohua.dao.RoleDao;
import com.baohua.exception.BaohuaSystemException;
import com.baohua.model.Menu;
import com.baohua.model.Role;
import com.baohua.service.MenuService;
import com.baohua.service.RoleService;
import com.baohua.util.BeanUtils;

/**
 * RoleService的实现类
 * @author czp
 */

@Service("roleService")
public class RoleServiceImpl implements RoleService {

	/**
	 * 查询所有角色列表
	 */
	public List<Role> queryRole() {
		return roleDao.queryRole("from Role");
	}

	/**
	 * 增加角色
	 * @param role
	 * @param  menuNOStr 菜单树Id所组成的字符串
	 * @throws Exception 
	 */
	public void addRole(Role role,String menuNOStr) throws BaohuaSystemException {
		Role r = roleDao.queryRoleByRoleName(role.getRoleName());
		//判断名称是否有重复，没有重复增加角色
		if(r == null) {
			//菜单树Id所组成的字符串进行解析为Set<Menu>，并将其加入到role中
			analyzeMenuNOs(role, menuNOStr);
			roleDao.addRole(role);
		}else {
			throw new BaohuaSystemException("角色名称已经存在");
		}
	}

	/**
	 * 修改角色
	 * @param role 角色对象
	 * @param  menuNOStr 菜单树Id所组成的字符串
	 */
	public void updateRole(Role role, String menuNOStr) throws BaohuaSystemException {
		//判断是否存在此对象
		Role r = roleDao.queryRoleById(role.getRoleId());
		if(r != null) {
			//判断本身的名称有没有修改
			if(role.getRoleName().equals(r.getRoleName())) {
				//没有修改名称判断是否没有修改其他字段, 没有发现修改就不进行update
				if(!BeanUtils.compareObject(role, r)) {
					//拷贝属性
					copyRole(role, r);
					//菜单树Id所组成的字符串进行解析为Set<Menu>，并将其加入到role中
					analyzeMenuNOs(r, menuNOStr);
					roleDao.updateRole(r);
				}
		  }else {
			  //名称修改, 判断名称是否有重复
				Role roleByname = roleDao.queryRoleByRoleName(role.getRoleName());
				//如果没有重复就执行update
				if(roleByname==null) {
					//拷贝属性
					copyRole(role, r);
					//菜单树Id所组成的字符串进行解析为Set<Menu>，并将其加入到role中
					analyzeMenuNOs(r, menuNOStr);
					roleDao.updateRole(r);
				}else {
					//有同名, 报异常
					throw new BaohuaSystemException("角色名称已经存在");
				}
			}
			
		}else {
			throw new BaohuaSystemException("修改的角色不存在");
		}
		
	}

	/**
	 * 删除角色
	 * @param roleId 角色ID
	 */
	public void delRole(int roleId) throws BaohuaSystemException {
		Role r = roleDao.queryRoleById(roleId);
		if(r != null) {
			roleDao.delRole(r);
		}else {
			throw new BaohuaSystemException("角色不存在");
		}
	}

	/**
	 * 根据roleId查询角色
	 */
	public Role queryRoleById(int roleId) throws BaohuaSystemException {
		Role r = roleDao.queryRoleById(roleId);
		return r;
	}
	
	/**
	 * 根据roleId查询角色所对应的菜单树
	 * @param roleId 角色ID
	 */
	@Override
	public Set<Menu> queryMenuByRoleId(int roleId) throws BaohuaSystemException {
		Set<Menu> menus = new HashSet<Menu>();
		//查询角色
		Role role = queryRoleById(roleId);
			//获取角色所对象的菜单
			Set<Menu> childMenu = role.getMenus();
			for(Menu menu : childMenu) {
				//如果菜单是父节点,将其子节点也加入到menus中
				if(!menu.isLeaf()) {
					menus.add(menu);
					List<Menu> ms = menuService.queryMenuByParentNO(menu.getMenuNO());
					menus.addAll(ms);
				}else {
					menus.add(menu);
				}
			}
		return menus;
	}
	
	/**
	 * 菜单树Id所组成的字符串进行解析为Set<Menu>，并将其加入到role中
	 * @param role
	 * @param menuNOStr
	 * @return
	 */
	private Role analyzeMenuNOs(Role role, String menuNOStr) {
		//获取传过来的菜单Id字符串
		if(!StringUtils.isBlank(menuNOStr)) {
			Set<Menu> menus = new HashSet<Menu>();
			String[] menuNOs = menuNOStr.split(",");
			for(String menuNO : menuNOs) {
				menus.add(menuService.queryMenuByMenuNO(menuNO));
			}
			role.setMenus(menus);
		}
		return role;
	}
	
	/**
	 * 拷贝属性, 将role的属性copy到r中
	 * @param role
	 * @param r
	 */
	private void copyRole(Role role, Role r) {
		BeanUtils.copyProperty(role, r);
		r.setMenus(role.getMenus());
		r.setStaffs(role.getStaffs());
	}
	
	
	private RoleDao roleDao;
	private MenuService menuService;
	
	public MenuService getMenuService() {
		return menuService;
	}
    @Resource(name="menuService")
	public void setMenuService(MenuService menuService) {
		this.menuService = menuService;
	}

	public RoleDao getRoleDao() {
		return roleDao;
	}

	@Resource(name="roleDao")
	public void setRoleDao(RoleDao roleDao) {
		this.roleDao = roleDao;
	}

}
